package com.wntime.simulator.listener;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wntime.simulator.device.DeviceService;
import com.wntime.simulator.device.LevelDBService;
import com.wntime.simulator.device.Simulator;
import com.wntime.simulator.domain.SimulationField;
import com.wntime.simulator.service.SimulationFieldService;
import com.wntime.simulator.service.SimulatorService;
import com.wntime.simulator.utils.JacksonUtils;
import lombok.extern.slf4j.Slf4j;
import org.iq80.leveldb.DB;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Component
@Slf4j
public class CommandListener implements CommandLineRunner {

    @Autowired
    private DB db;

    @Value("${levelDbToPg:false}")
    private Boolean levelDbToPg;

    @Value("${extendUpdate:false}")
    private Boolean extendUpdate;

    @Autowired
    private DeviceService deviceService;

    @Autowired
    private SimulatorService simulatorService;

    @Autowired
    private SimulationFieldService fieldService;

    @Autowired
    private LevelDBService levelDBService;


    @Override
    public void run(String... args) throws Exception {

        if (levelDbToPg) {
            List<String> sims = levelDBService.getSims();
            for (String sim : sims) {
                List<com.wntime.simulator.device.SimulationField> fields = levelDBService.getFields(sim);
                Simulator simulator = levelDBService.getSimula(sim);
                this.saveDatabase(simulator);
            }
        }

        if (extendUpdate) {
            List<SimulationField> fields = fieldService.list();
            for (SimulationField field : fields) {

                List<Map<String, Object>> ext = new ArrayList<>();
                HashMap<String, Object> map = new HashMap<>();
                map.put("start", "00:00");
                map.put("end", "23:59");
                map.put("min", field.getBefore());
                map.put("max", field.getAfter());
                ext.add(map);
                field.setExtendInfo(JacksonUtils.toJson(ext));
                fieldService.updateById(field);

            }
        }

        List<com.wntime.simulator.domain.Simulator> simulators = simulatorService.list();
        for (com.wntime.simulator.domain.Simulator simulator : simulators) {
            deviceService.initial(toSimulator(simulator));
            QueryWrapper<SimulationField> wrapper = new QueryWrapper<>();
            wrapper.eq("simulator_id", simulator.getId());
            List<SimulationField> fields = fieldService.list(wrapper);
            deviceService.resetField(simulator.getId(), toSimulatorFields(fields));
        }
    }

    private List<com.wntime.simulator.device.SimulationField> toSimulatorFields(List<SimulationField> fields) {
        return fields.stream().map(SimulationField::toSimulatorField).collect(Collectors.toList());
    }

    private Simulator toSimulator(com.wntime.simulator.domain.Simulator simulator) {
        return simulator.toSimulator();
    }

    private void saveDatabase(Simulator simulator) throws Exception {
        com.wntime.simulator.domain.Simulator entity = new com.wntime.simulator.domain.Simulator();
        entity.setId(Long.parseLong(simulator.getId()));
        entity.setName(simulator.getName());
        entity.setType(simulator.getType());
        entity.setPort(simulator.getPort());
        entity.setPoolSize(simulator.getPoolSize());
        entity.setOverTcp(simulator.getOverTcp());
        entity.setUintId(simulator.getUintId());
        simulatorService.save(entity);
        log.info("save simulator {}", simulator.getId() + " " + simulator.getName());

        List<com.wntime.simulator.device.SimulationField> fields = levelDBService.getFields(simulator.getId());
        for (com.wntime.simulator.device.SimulationField field : fields) {
            com.wntime.simulator.domain.SimulationField sfd = new com.wntime.simulator.domain.SimulationField();
            sfd.setSimulatorId(entity.getId());
            sfd.setRef(field.getRef());
            sfd.setName(field.getName());
            sfd.setBefore(field.getBefore());
            sfd.setAfter(field.getAfter());
            sfd.setChange(field.getChange());
            fieldService.save(sfd);
        }
        log.info("save fields {}", fields.size());
    }
}
